from Bases import BaseObject, ChildGroup
from basepage import BasePage
from .. import widgets

class DeviceControl(BasePage):
    page_name = 'Device Control'
    def __init__(self, **kwargs):
        super(DeviceControl, self).__init__(**kwargs)
        self.build_topwidget('Label', name='DeviceControl')
        bounds = [.3, self.y_offset, .7, .7]
        self.selected_controls = self.topwidget.add_widget(SelectedGroupControls, parent=self, bounds=bounds)
        self.device_select = self.topwidget.add_widget(DeviceSelect, parent=self)
        self.device_select.bind(selection_changed=self.on_device_selection_changed)
        self.topwidget.refresh_interface()
        
    def on_device_selection_changed(self, **kwargs):
        print 'selection_changed: ', kwargs
        self.selected_controls.set_group(kwargs.get('device'))
        
class DeviceSelect(widgets.Label):
    def __init__(self, **kwargs):
        self.parent = kwargs.get('parent')
        self.current_device = None
        self.current_device_index = None
        kwargs.setdefault('osc_parent_node', self.parent.osc_node)
        kwargs.setdefault('name', 'select_buttons')
        bounds = [self.parent.x_offset, self.parent.y_offset, .2, .8]
        kwargs.setdefault('bounds', bounds)
        super(DeviceSelect, self).__init__(**kwargs)
        self.register_signal('selection_changed')
        self.rows = kwargs.get('rows', 8)
        self.columns = kwargs.get('columns', 2)
        self.buttons = []
        w = self.bounds[2] / self.columns
        h = self.bounds[3] / self.rows
        i = 0
        for row in range(self.rows):
            for col in range(self.columns):
                i += 1
                bounds = [col * w + self.bounds[0], row * h + self.bounds[1], w, h]
                btn = self.add_widget(DeviceSelectBtn, index=i, iOsc=self.parent.iOsc, bounds=bounds)
                btn.bind(touch_state=self.on_btn_touch_state)
                self.buttons.append(btn)
                
    def unlink(self):
        #for btn in self.buttons:
        #    btn.unlink()
        super(DeviceSelect, self).unlink()
        
    def set_current_device(self, index):
        device = self.parent.MainController.DeviceSystem.PatchedDevices.get(index)
        if device is None:
            if self.current_device is not None:
                return
            index = None
        self.current_device_index = index
        if device != self.current_device:
            self.current_device = device
            self.emit('selection_changed', device=device, index=index)
            
            
    def update_btn_states(self):
        current = self.current_device_index
        for btn in self.buttons:
            btn.touch_state = btn.index == self.current_device_index
            
    def on_btn_touch_state(self, **kwargs):
        btn = kwargs.get('obj')
        state = kwargs.get('value')
        if state:
            self.set_current_device(btn.index)
        elif btn.index == self.current_device_index:
            self.set_current_device(None)
        self.update_btn_states()
        
class DeviceSelectBtn(widgets.Toggle):
    def __init__(self, **kwargs):
        self.iOsc = kwargs.get('iOsc')
        self.DeviceSystem = self.iOsc.MainController.DeviceSystem
        self.index = kwargs.get('index')
        kwargs.update({'name':str(self.index), 'label':str(self.index)})
        super(DeviceSelectBtn, self).__init__(**kwargs)
        self.device = None
        device = self.DeviceSystem.PatchedDevices.indexed_items.get(self.index)
        if device:
            self.set_device(device)
        self.DeviceSystem.PatchedDevices.bind(child_update=self.on_PatchedDevices_update)
        
    def unlink(self):
        self.DeviceSystem.PatchedDevices.unbind(self.on_PatchedDevices_update)
        self.set_device(None)
        super(DeviceSelectBtn, self).unlink()
        
    def set_device(self, device):
        if self.device is not None:
            self.device.unbind(self.on_device_name_change)
        self.device = device
        if self.device is not None:
            self.label = device.name
            self.device.bind(name=self.on_device_name_change)
        else:
            self.label = str(self.index)
            
    def on_device_name_change(self, **kwargs):
        self.label = self.device.name
    
    def on_PatchedDevices_update(self, **kwargs):
        device = self.DeviceSystem.PatchedDevices.indexed_items.get(self.index)
        self.set_device(device)
        
class SelectedGroupControls(widgets.Label):
    def __init__(self, **kwargs):
        self.parent = kwargs.get('parent')
        self.group = None
        kwargs.setdefault('osc_parent_node', self.parent.osc_node)
        kwargs.setdefault('name', 'selected_controls')
        super(SelectedGroupControls, self).__init__(**kwargs)
        
        self.controls = {}
        bounds = self._scale_bounds([.1, 0, .1, 1.])
        self.controls['Dimmer'] = self.add_widget(widgets.VSlider, bounds=bounds, name='dimmer', label='Dimmer')
        bounds = self._scale_bounds([.5, 0., .5, .5])
        self.controls['Position'] = self.add_widget(widgets.xyPad, name='xy', bounds=bounds)#, min=-1., max=1.)
        h = .1
        bounds = self._scale_bounds([.5, .6, .5, .3])
        self.controls['Color'] = self.add_widget(widgets.ColorSlider, name='color', bounds=bounds)
#        for i, key in enumerate(['red', 'green', 'blue']):
#            bounds = self._scale_bounds([.5, i * h + .6, .5, h])
#            ckwargs = dict(name=key, bounds=bounds, min=0, max=255)
#            col = [0]*3
#            col[i] = 255
#            ckwargs['foregroundColor'] = col
#            col = [0]*3
#            col[i] = 96
#            ckwargs['backgroundColor'] = col
#            control = self.add_widget(widgets.HSlider, **ckwargs)
#            self.controls[key] = control
        #self.test = self.add_widget(widgets.Button, bounds=self._scale_bounds([.5, .2, .2, .2]), name='test')
        
    def unlink(self):
        self.set_group(None)
        super(SelectedGroupControls, self).unlink()
        
    def set_group(self, group):
        #if self.group:
        #    for key in ['red', 'green', 'blue', 'Dimmer']:
        #        self.controls[key].set_src_object()
        self.group = group
        if self.group:
            for key, control in self.controls.iteritems():
                if group.saved_class_name == 'PatchedDevice':
                    agroup = group.Groups.get(key)
                else:
                    agroup = group.AttributeGroups.get(key)
                if agroup is None:
                    control.Property = None
                    continue
                control.Property = (agroup, getattr(agroup, 'value_attribute', 'value'))
            #self.controls['Dimmer'].set_src_object(src_object=group.AttributeGroups['Dimmer'], src_attr='value', src_signal='value_changed')
            #for key in ['red', 'green', 'blue']:
            #    self.controls[key].set_src_object(src_object=group.AttributeGroups['Color'], src_attr=key, src_signal='value_changed')
            #self.xyValueObj.set_src_object(group.AttributeGroups['Position'])
        else:
            for control in self.controls.itervalues():
                control.Property = None
            
    def _scale_bounds(self, bounds):
        return [(bounds[0]*self.width) + self.x, (bounds[1]*self.height) + self.y, 
                 bounds[2]*self.width, bounds[3]*self.height]
                 
class XYValueObject(BaseObject):
    _Properties = {'value':dict(default=[0., 0.], quiet=True)}
    def __init__(self, **kwargs):
        self.value_min = -1.
        self.value_max = 1.
        self.value_set_by_group = False
        self.scale = {'pan':2., 'tilt':2.}
        super(XYValueObject, self).__init__(**kwargs)
        self.src_object = None
        self.bind(value=self.on_value_set)
        
    def unlink(self):
        self.set_src_object(None)
        super(XYValueObject, self).unlink()
        
    def set_src_object(self, obj):
        if self.src_object:
            self.src_object.unbind(self.on_group_value_changed)
        self.src_object = obj
        if self.src_object:
            self.scale['pan'] = self.src_object.pan_range
            self.scale['tilt'] = self.src_object.tilt_range
            self.src_object.bind(value_changed=self.on_group_value_changed)
            
    def on_value_set(self, **kwargs):
        if self.value_set_by_group:
            self.value_set_by_group = False
            return
        pos = kwargs.get('value')
        for i, key in enumerate(['pan', 'tilt']):
            val = pos[i] * self.scale[key] / 2.
            if val != getattr(self.src_object, key):
                setattr(self.src_object, key, val)
                
    def on_group_value_changed(self, **kwargs):
        pos = [getattr(self.src_object, key) * 2. / self.scale[key] for key in ['pan', 'tilt']]
        if pos != self.value:
            self.value_set_by_group = True
            self.value = pos
